package com.cpkf.basis.soapToCsv;

import java.io.File;
import java.io.FileWriter;
import java.io.Serializable;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import au.com.bytecode.opencsv.CSVWriter;

/**
 *get affiliate window report each week from WSDL interface
 *
 * @author Hyman Hu
 * @since  2014-9-9
 * Copyright SHOP.COM: all rights reserved worldwide
 */
public class AffiliateWindowReportTask implements Serializable {
	
	private static final long serialVersionUID = -3597759282802754719L;
	private long timeout = 0;
	private boolean isOk = true;
	private String userId = "63268";
	private String pwd = "1cb2fb7a19c35feb5e5eed5c273e6a0af6eb18c6ad950a67";
	private String sType = "affiliate";
	private String region = "UK";
	private String filePath = "\\ccsqlreports1\\NonDBData\\AffiliateReports\\%sAffiliateWindow";
	private static final String WSDL_URL = "http://api.affiliatewindow.com/v4/AffiliateService";

	/**
	 * call the interface from WSDL and get response
	 * @param startDate  			before 7 days
	 * @param endDate 				now time
	 * @return SOAPMessage			soap message from WSDL
	 * @throws Exception
	 */
	private SOAPMessage callWSDL(String startDate, String endDate) throws Exception {
		/* create SOAPMessage object */
		MessageFactory messageFactory = MessageFactory.newInstance();
        SOAPMessage soapMessage = messageFactory.createMessage();
        SOAPPart soapPart = soapMessage.getSOAPPart();
        SOAPEnvelope envelope = soapPart.getEnvelope();
        
        envelope.addNamespaceDeclaration("api", "http://api.affiliatewindow.com/");
        
        SOAPHeader headerElement = envelope.getHeader();
        SOAPElement quota = headerElement.addChildElement("getQuota", "api");
        quota.setAttribute("SOAP-ENV:mustUnderstand", "1");
        quota.setAttribute("SOAP-ENV:actor", "http://api.affiliatewindow.com/");
        quota.setAttribute("xmlns:SOAP-ENV", "SOAP-ENV");
        quota.addTextNode("true");
        SOAPElement userAuthentication = headerElement.addChildElement("UserAuthentication", "api");
        userAuthentication.addChildElement("iId", "api").addTextNode(userId);
        userAuthentication.addChildElement("sPassword", "api").addTextNode(pwd);
        userAuthentication.addChildElement("sType", "api").addTextNode(sType);
        
        SOAPBody bodyElement = envelope.getBody();
        SOAPElement transactionList = bodyElement.addChildElement("getTransactionList", "api");
        transactionList.addChildElement("dStartDate", "api").addTextNode(startDate);
        transactionList.addChildElement("dEndDate", "api").addTextNode(endDate);
        transactionList.addChildElement("sDateType", "api").addTextNode("transaction");
        
        soapMessage.saveChanges();
        
        /* Print the request message */
        System.out.print("Request SOAP Message: ");
        soapMessage.writeTo(System.out);
        System.out.println();
        
        /* create connection */
        SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
        SOAPConnection soapConnection = soapConnectionFactory.createConnection();
        
        /* get soap response */
        SOAPMessage soapResponse = soapConnection.call(soapMessage, new URL(WSDL_URL));
        
        /* close connection */
        soapConnection.close();
        
		return soapResponse;
	}
	
	/**
	 * write to local file when get response
	 * @param filePath				file's directory
	 * @throws Exception			
	 */
	private void saveFile(String filePath) throws Exception {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		String endDate = sdf.format(calendar.getTime());
		calendar.add(Calendar.DAY_OF_YEAR, -6);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		String startDate = sdf.format(calendar.getTime());
		
		SOAPMessage soapResponse = callWSDL(startDate, endDate);
		List<String[]> alList = getFileData(soapResponse);
		
		String fileName = String.format("%s%s%s%s%s", "affiliate-report", startDate.substring(0, startDate.indexOf("T")), "~", endDate.substring(0, endDate.indexOf("T")), ".csv");
		File directory = new File(filePath);
		if (!directory.exists()) {
			directory.mkdir();
		}
		CSVWriter writer = new CSVWriter(new FileWriter(new File(String.format("%s%s%s", filePath, "\\", fileName))),',');
		
		writer.writeAll(alList);  
		writer.close();
	}
	
	/**
	 * get csv file data from SOAPMessage
	 * @param soapResponse		response from soap
	 * @return					List<String[]>
	 * @throws Exception
	 */
	private List<String[]> getFileData(SOAPMessage soapResponse) throws Exception {
		NodeList nodeList = soapResponse.getSOAPBody().getElementsByTagName("ns1:Transaction");
		List<String[]> alList = new ArrayList<String[]>();
		List<String> header = new ArrayList<String>();
		List<String> body = new ArrayList<String>();
		
		if (nodeList.getLength() == 0) {
			return alList;
		} else {
			Node node = nodeList.item(0);
			NodeList childrenList = node.getChildNodes();
			for (int i = 0; i < childrenList.getLength(); i++) {
				String nodeKey = childrenList.item(i).getNodeName();
				if (!"ns1:aTransactionParts".equals(nodeKey)) {
					header.add(nodeKey.substring(nodeKey.indexOf(":") + 1, nodeKey.length()));
				}
			}
			alList.add(header.toArray(new String[header.size()]));
		}
		
		for (int i = 0; i < nodeList.getLength(); i++) {
			body = new ArrayList<String>();
			Node node = nodeList.item(i);
			for (int j = 0; j < header.size(); j++) {
				Node childNode = getNodeByName(node, String.format("%s%s", "ns1:", header.get(j)));
//				body.add(childNode == null ? "" : childNode.getTextContent());
				body.add(childNode == null ? "" : childNode.getNodeValue());
			}
			alList.add(body.toArray(new String[body.size()]));
		}
		
		return alList;
	}
	
	/**
	 * get node by name
	 * 
	 * @param parentNode	parent node
	 * @param name			node name
	 * @return Node
	 */
	public static Node getNodeByName(Node parentNode, String name) {
		Node node = null;
		if (parentNode == null) {
			return node;
		}
		
		NodeList nodeList = parentNode.getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node childNode = nodeList.item(i);
			if (name.equals(childNode.getNodeName())) {
				node = childNode;
				break;
			}
			node = getNodeByName(childNode, name);
			if (node != null) {
				break;
			}
		}
		
		return node;
	}
	
	public static void main(String[] args) {
	}
	
}
